﻿using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;

namespace SimpleRedisClinet
{
    /// <summary>
    /// socket pool
    /// yangmeng(hvbird@gmail.com)
    /// 2011-01-21
    /// </summary>
    internal class SocketPool
    {
        private static SocketPool m_pool;
        private static LogInterface m_log;
        private List<MySocket> m_list;

        public SocketPool()
        {
            m_list = new List<MySocket>();
        }

        public MySocket GetSocket(string ip,int port)
        {
            MySocket ret =null;

            lock (this)
            {
                foreach (MySocket socket in m_list)
                {
                    if (!socket.Used)
                    {
                        ret = socket;
                        ret.Used = true;
                        break;
                    }
                }
            }

            if (ret == null)
            {
                ret = new MySocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                ret.Used = true;
                ret.SendTimeout = 2000;
                ret.ReceiveTimeout = 2000;
                ret.Connect(ip, port);
                lock (this)
                {
                    m_list.Add(ret);
                }
            }
            else
            {
                if (!ret.Connected)
                {
                    RemoveSocket(ret);

                    ret = new MySocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    ret.Used = true;
                    ret.SendTimeout = 2000;
                    ret.ReceiveTimeout = 2000;
                    ret.Connect(ip, port);
                    lock (this)
                    {
                        m_list.Add(ret);
                    }
                }
            }


            return ret;
        }

        public void RemoveSocket(MySocket sock)
        {
            try
            {
                sock.Shutdown(SocketShutdown.Both);
                sock.Close();
            }
            catch (Exception ex)
            {

            }
            

            lock (this)
                m_list.Remove(sock);
        }

        public static SocketPool Instance
        {
            get
            {
                if (m_pool == null)
                {
                    m_pool = new SocketPool();
                }

                return m_pool;
            }
        }

        public static void Init()
        {
            if (m_pool == null)
            {
                m_pool = new SocketPool();
            }
        }

        public static LogInterface Log
        {
            set { m_log = value; }
            get { return m_log; }
        }

    }

    public class MySocket : Socket
    {
        private bool m_used;

        public MySocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
            : base(addressFamily, socketType, protocolType)
        {

        }

        public bool Used
        {
            get { return m_used; }
            set { m_used = value; }
        }
    }
}
